16章 ループの制御
tommy.icon
「ループ」とは、何らかの反復的な制御構造、つまりプログラムがコードブロックを繰り返し実行する構造の通称である。
プログラミングの最も複雑な側面の1つ
16.1 ループの種類の選択
ループの種類
カウントループ
連続評価ループ
エンドレスループ
反復子ループ
(イテレータ)
while ループを使用する状況
先頭で評価するループ
末尾で評価するループ
do-while
ループの途中に出口があるループを使用する状況
1.5 回実行するループを while (true) と break を利用して書く
注意点
終了条件はすべて 1 か所にまとめる
コメントを使う
「ループの途中に出口がある」ループは、入口が 1 つ、出口が 1 つの構造化された制御構造であり、それがループ制御のあるべき姿
tommy.icon そうなのかぁ
goto を使った誤った「ループの途中に出口がある」ループ
for ループを使用する状況
インデックスの値を明示的に変更してループを強制的に終了してはならない
そうした場合は while ループを使う
foreach ループを使用する状況
ループを繰り返すための計算がいらないため、そのことが原因でエラーになる可能性がない
16.2 ループの制御
ループの問題を防ぐ
ループに影響する要因の数を最小限に抑える
ループの内部をルーチンとして扱う
ループはブラックボックスと考える
ループの開始
ループの入り口は 1 か所にする
初期化コードはループの直前に置く
無限ループには while (true) を使用する
for ( ; ; ) でも構わない
for ループが適している状況には for ループを使用する
while ループの方が適している状況では for ループを使用しない
ループの進行を制御しないステートメントはヘッダーに置かない
ループ本体の処理
ループのステートメントは { と } で囲む
空のループを使わない
ループの前処理や後処理はループの先頭または末尾にまとめる
ループの 1 回の処理は 1 つの機能に絞る
tommy.icon これはリファクタリング本でも出てきたな
tommy.icon パフォーマンスが気になるかもしれないがむしろ分けることで最適化しやすくなるというやつ
ループの終了
ループが終了することを確認する
ループの終了条件を明確にする
for ループを終了させるためにループ変数を勝手に書き換えない
ループ変数の最終値を使用するコードを書かない
安全カウンタの使用を検討する
リープの繰り上げ終了
while ループでは、ブール変数のフラグではなく break 文の使用を検討する
ループを break 文だらけにしない
continue 文はループの先頭での評価に使用する
言語がラベル付きの break 文をサポートしている場合は、それを使用する
break 文と continue 文の使用には注意する
使う理由を説明できないのなら使わないこと
エンドポイントの確認
有能なプログラマは、頭の中でシミュレーションし、電卓で計算する
有能でないプログラマは、いろいろな組み合わせをでたらめに試して、うまくいきそうなものを見つけようとする傾向にある
ループ変数の使用
配列やループの限界値には序数または列挙を使用する
ネストしたループが読みやすくなるよう、変数に意味のある名前を付ける
tommy.icon これは前にも書かれてた
意味のある名前を使って、ループ変数のクロストークを防ぐ
tommy.icon これも
ループ変数のスコープはループ自体に制限する
ループの適切な長さ
ループは一度に確認できる程度に短くする
ネストは 3 段階までに制限する
長いループの内部構造をルーチンにする
tommy.icon 短くすることにも繋がりそう
長いループは特に明確にする
16.3 ループの作成 ― 内から外へ
「第9章 擬似コードによるプログラミング」と同じプロセス
より一般的で複雑なループを作成する場合は小さくて理解しやすいものから取り組む
16.4 ループと配列の対応付け
配列の乗算の例(APL)
tommy.icon APL って初めて聞いたけどこんなことできるのか
16.5 まとめ
ループは複雑なため、単純に保ってコードの読み手の助けとする
ループを単純に保つコツ
変わったループを作成しない
ネストをできるだけ少なくする
入り口と出口を明確にする
前処理や後処理のコードを 1 箇所にまとめる
ループ変数にはわかりやすい名前を付け、1 つの目的にのみ使用する
すべてのケースで正常に実行されることと、どのような条件でも終了することを全体を見て検証する